package other.system.client.oa.submit;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rkhd.platform.sdk.data.model.Contract;
import com.rkhd.platform.sdk.data.model.ReceivablePlan__c;
import com.rkhd.platform.sdk.exception.ApiEntityServiceException;
import com.rkhd.platform.sdk.exception.ScriptBusinessException;
import com.rkhd.platform.sdk.log.Logger;
import com.rkhd.platform.sdk.log.LoggerFactory;
import com.rkhd.platform.sdk.service.XoqlService;
import org.apache.commons.lang.StringUtils;
import other.system.client.util.HCDateUtils;
import other.system.client.util.HCXObjectService;
import other.system.client.util.ResultBody;
import other.system.client.util.TfReturnMsgTools;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 提交合同审批数据到OA
 * @Author: 黎炎松
 * @Date: 2024/7/9 17:39
 */
public class SubmitContract extends SubmitSuper {

    private static HCXObjectService hcxObjectService = new HCXObjectService();

    private static XoqlService xoqlService = XoqlService.instance();

    private static final String LOGGER_MSG = "推送合同审批数据到OA ==> ";

    private static final Logger logger = LoggerFactory.getLogger();

    public static void main(String[] args) throws ApiEntityServiceException, ScriptBusinessException {
        SubmitContract submitContract = new SubmitContract();
        //submitContract.pushContractToOA(3985021206485653L); // 合同
        //submitContract.pushOrderToOA(3746032667122253L, 1); // 订单

        // 需切换测试环境进行测试，正式环境发送会导致他们的人员账号收到审批提醒
        //submitContract.pushOrderToOA(3433214006958681L, 1); // deBooking
    }

    /**
     * 推送订单数据到OA审批 order 合同推送的是1号订单 订单推送的是非1号订单 共用OA合同模版
     * @param dataId （pushType 1: 代表订单id  2:代表deBookingId）
     * @param pushType 1:订单推送 2：deBooking推送（deBooking推送与正常订单的区别在于 1.是否退款 2.退款金额 3：订单明细取debooking中的明细，金额取deBooking的金额 负数推送过去）
     * @return
     */
    public String pushOrderToOA(Long dataId, int pushType) {
        try {
            logger.info(LOGGER_MSG + "非1号订单推送处理开始: " + dataId + " pushType: " + pushType);
            String sql = "";
            Long orderId = dataId; // 订单id
            Long deBookingId = null; // deBookingId
            JSONObject debooking = null; // deBooking 对象
            if (pushType == 2) {
                sql = "select id,order__c,oaApprovalStatus__c,oaApprovalId__c,debookingAnnex__c,YNrefund__c from debooking__c where id = " + dataId;
                debooking = xoqlService.query(sql, true).getRecords().get(0);
                deBookingId = dataId;
                orderId = debooking.getLong("order__c");
            }


            // 合同推送的是1号订单 订单推送的是非1号订单
            sql = "select id,po,contractId.title title,opportunityId.opportunityName opportunityName,opportunityId.pmsProjectCode__c pmsProjectCode__c,finalCustomerName__c.accountName accountName," +
                    "contractId.ourCompanyName__c.name ourCompanyName,amount,orderAmount__c,responsibleSelling__c.name responsibleSellingName," +
                    "deliveryManager__c.name deliveryManagerName,deliveryManager__c.LoginName__c zrrOaAccount,deliveryManager__c.personalEmail zrrOaEmail," +
                    "departmentTeam__c,annex__c,contractId.taxRegistrationNo__c taxRegistrationNo__c,contractId.contractBackground__c contractBackground__c," +
                    "comment,oaApprovalId__c,oaApprovalStatus__c,entityType,countersignNode__c.LoginName__c oaAccount,countersignNode__c.personalEmail oaEmail," +
                    "ownerId.LoginName__c ownerOaAccount,ownerId.personalEmail ownerOaEmail,approximateSum__c,contractId.paymentMethod__c paymentMethod__c " +
                    " from _order where id = " + orderId;

            List<JSONObject> orderRecords = xoqlService.query(sql, true).getRecords();
            if (orderRecords == null || orderRecords.size() <= 0) {
                logger.error(LOGGER_MSG + "获取订单数据异常");
                return TfReturnMsgTools.getFailResult("获取订单数据异常");
            }

            // 获取订单参数
            JSONObject order = orderRecords.get(0);
            String contractTitle = order.getString("title");
            Long entityType = order.getLong("entityType");
            String oaApprovalId = order.getString("oaApprovalId__c");
            String oaApprovalStatus = getOptionStr(order.getJSONArray("oaApprovalStatus__c"));
            // 如果是deBooking推送则审批数据取deBooking
            if (pushType == 2) {
                oaApprovalId = debooking.getString("oaApprovalId__c");
                oaApprovalStatus = getOptionStr(debooking.getJSONArray("oaApprovalStatus__c"));
            }

            // 如果是 作废 状态，则重新提交
            if (Objects.equals(oaApprovalStatus, "作废")) {
                oaApprovalId = "";
            }

            // 判断业务类型  只推送 项目订单: 3309750193298054  预交付订单: 3309752318565039
            //List<Long> typeList = Arrays.asList(3309750193298054L, 3309752318565039L);
            //if (!typeList.contains(entityType)) {
            //    logger.info(LOGGER_MSG + "当前订单业务类型不可提交OA审批");
            //    return TfReturnMsgTools.getFailResult("当前订单业务类型不可提交OA审批");
            //}

            // 判断 【所属部门/团队】 是否为空，进行提示
            String departmentTeamVal = order.getString("departmentTeam__c");
            if (StringUtils.isBlank(departmentTeamVal)) {
                logger.error(LOGGER_MSG + "当前数据【所有人】部门下的'项目所属部门团队'为空，请联系管理员进行配置");
                return TfReturnMsgTools.getFailResult("当前数据【所有人】部门下的'项目所属部门团队'为空，请联系管理员进行配置");
            }

            // 拼接表单数据
            JSONObject formObject = new JSONObject();

            // 前置条件:需要判断是否有应收计划明细 获取当前订单的应收计划明细 阶段: receivableNode__c  比列：receivableRatio__c
            sql = "select id,receivableNode__c,receivableRatio__c,scheduledDueDate__c,paymentPeriod__c from receivablePlanDetail__c where order__c = " + orderId;
            List<JSONObject> receivableList = xoqlService.query(sql, true).getRecords();
            if (receivableList.size() <= 0) {
                logger.error(LOGGER_MSG + "当前订单收款计划明细数据不可为空");
                return TfReturnMsgTools.getFailResult("当前订单收款计划明细数据不可为空");
            }

            // 判断比例必须为100
            //double receivableRatio = receivableList.stream().mapToDouble(v -> v.getDouble("receivableRatio__c")).sum();
            double receivableRatio = receivableList.stream().map(v -> new BigDecimal(v.getString("receivableRatio__c"))).collect(Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)).doubleValue();
            logger.info(LOGGER_MSG + "receivableRatio: " + receivableRatio);
            if (receivableRatio != 1) {
                logger.error(LOGGER_MSG + "当前订单收款明细比例需为100%");
                return TfReturnMsgTools.getFailResult("当前订单收款明细比例需为100%");
            }

            // 获取订单明细信息
            sql = "select id,productCode__c,productId.productName productName,productNameB__c,specificationModel__c," +
                    "unitA__c,quantity2__c,unitPrice,SF_SL__c,contractUntaxedA__c,priceTotal,servicePeriod__c,lineRemarks__c " +
                    " from orderProduct where orderId = " + orderId;
            List<JSONObject> orderProductList = xoqlService.query(sql).getRecords();
            logger.info(LOGGER_MSG + "orderProductList: " + orderProductList.size());

            // 获取应收计划
            sql = "select id,other__c from receivablePlan__c where order__c = " + orderId;
            ReceivablePlan__c receivablePlan = hcxObjectService.queryOne(sql, ReceivablePlan__c.class);


            // 拼接表单的数据
            formObject.put("fd_37b1f02aacb484", contractTitle); // 合同名
            formObject.put("fd_37b1f02d50a79a", order.getString("opportunityName")); // 项目名称
            formObject.put("fd_37b1f027894174", order.getString("accountName")); // 合同甲方
            formObject.put("fd_37b1f063443544", order.getString("pmsProjectCode__c")); // pms项目编码
            formObject.put("fd_37b1f05f564030", order.getString("ourCompanyName")); // 合同乙方
            formObject.put("fd_37b1f05c89b21a", order.getString("po")); // 销售合同编号（订单号）
            formObject.put("fd_37b1f0301f8496", order.getString("amount")); // 合同含税总额
            formObject.put("fd_3a436ef485955a", order.getString("orderAmount__c")); // 合同未税总额
            formObject.put("fd_37b1f02600eec6", order.getString("responsibleSellingName")); // 责任销售

            formObject.put("fd_3a436f05f790b6", order.getString("deliveryManagerName")); // 交付负责人
            JSONObject oaAccount = getOaAccount(order, 3);
            formObject.put("fd_3d354f220f6d4a", oaAccount == null ? null : oaAccount.getString("LoginName")); // 交付负责人(账号)

            formObject.put("fd_38308d81c1ecc8", departmentTeamVal); // 所属部门/团队
            formObject.put("fd_3c8dfe4b57e75e", order.getString("taxRegistrationNo__c")); // 税号
            formObject.put("fd_3d3071a37fcad2", order.getString("approximateSum__c")); // 与报价概算是否一致
            formObject.put("fd_39edf9e4f6bc92", getOaAccount(order, 1)); // 加签
            formObject.put("fd_3d54962abdddae", getOptionStr(order.getJSONArray("paymentMethod__c"))); // 付款方式
            // 其他
            if (receivablePlan != null) {
                formObject.put("fd_3a76b77d94325c", receivablePlan.getOther__c());
            }

            // 判断是否是deBooking推送
            formObject.put("fd_3d3d202e1495fc", "否"); // 是否需退款
            formObject.put("fd_3d3d20289df1e6", ""); // 退款金额
            List<JSONObject> deBookingDetailList = new ArrayList<>();
            if (pushType == 2) {
                // 查询deBooking信息
                sql = "select id,amount__c,order_d1__c from debookingDetailed__c where debooking__c = " + deBookingId;
                deBookingDetailList = xoqlService.query(sql).getRecords();
                double refundAmount = deBookingDetailList.stream().map(v -> new BigDecimal(v.getString("amount__c"))).collect(Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)).doubleValue();
                String yNrefund = getOptionStr(debooking.getJSONArray("YNrefund__c"));
                if (StringUtils.isNotBlank(yNrefund)) formObject.put("fd_3d3d202e1495fc", yNrefund); // 是否需退款
                formObject.put("fd_3d3d20289df1e6", -refundAmount); // 退款金额
            }

            // 应收计划  1:预付 2：蓝图 3：上线 4：初验 5：终验 6：质保 7：其他
            JSONArray receivableDetailArr = new JSONArray();
            for (JSONObject receivable : receivableList) {
                JSONObject receivableDetail = new JSONObject();
                receivableDetail.put("fd_3d1c130b5b427a.fd_3d1c131b42b920", getOptionStr(receivable.getJSONArray("receivableNode__c"))); // 节点
                receivableDetail.put("fd_3d1c130b5b427a.fd_3d1c131d5e7a40", receivable.getDouble("receivableRatio__c") == null ? "0" : (receivable.getDouble("receivableRatio__c") * 100)); // 比列
                receivableDetail.put("fd_3d1c130b5b427a.fd_3d54964c296c42", getOptionStr(receivable.getJSONArray("paymentPeriod__c"))); // 账期
                Long scheduledDueDate = receivable.getLong("scheduledDueDate__c");
                if (scheduledDueDate != null) {
                    receivableDetail.put("fd_3d1c130b5b427a.fd_3d1c131e154274", HCDateUtils.longToString(scheduledDueDate, HCDateUtils.FORMATTIME)); // 时间
                }
                receivableDetailArr.add(receivableDetail);
            }
            formObject.put("fd_3d1c130b5b427a", receivableDetailArr);

            // 明细数据
            JSONArray orderDetailArr = new JSONArray();
            for (JSONObject orderProduct : orderProductList) {
                JSONObject orderDetailObj = new JSONObject();
                String taxRate = getOptionStr(orderProduct.getJSONArray("SF_SL__c")); // 税率

                // 判断是否是推送 deBooking
                if (pushType == 2) {
                    // 判断当前明细是否在deBooking明细中，不存在则不推送，存在需要调整合同金额为负数
                    JSONObject deBookingDetailData = deBookingDetailList.stream().filter(v -> Objects.equals(v.getLong("order_d1__c"), orderProduct.getLong("id"))).findFirst().orElse(null);
                    if (deBookingDetailData == null) {
                        continue;
                    }

                    // 设置金额 不含税 = 含税金额 / ( 1 + ( 税率 / 100) )
                    String amount = deBookingDetailData.getString("amount__c");
                    BigDecimal bgAmount = new BigDecimal(amount);
                    BigDecimal bgTaxRate = new BigDecimal(taxRate).divide(BigDecimal.valueOf(100));
                    double newAmount = bgAmount.divide(bgTaxRate.add(BigDecimal.valueOf(1)), BigDecimal.ROUND_CEILING, 2).doubleValue();
                    orderProduct.put("priceTotal", -bgAmount.doubleValue()); // 含税
                    orderProduct.put("contractUntaxedA__c", -newAmount); // 不含税
                }

                orderDetailObj.put("fd_3d10374c42992c.fd_3d10385af6aeb6", orderProduct.getString("productCode__c")); // 物料编码
                orderDetailObj.put("fd_3d10374c42992c.fd_3d10385d9be716", orderProduct.getString("productName")); // 产品名称（系统）
                orderDetailObj.put("fd_3d10374c42992c.fd_3d10385e2f70a8", orderProduct.getString("productNameB__c")); // 产品名称
                orderDetailObj.put("fd_3d10374c42992c.fd_3d10385ed6c3de", orderProduct.getString("specificationModel__c")); // 规则型号
                orderDetailObj.put("fd_3d10374c42992c.fd_3d10385f8deb48", orderProduct.getString("unitA__c")); // 单位
                orderDetailObj.put("fd_3d10374c42992c.fd_3d1038602d2196", orderProduct.getString("quantity2__c")); // 数量
                orderDetailObj.put("fd_3d10374c42992c.fd_3d103860ddf920", orderProduct.getString("unitPrice")); // 单价
                orderDetailObj.put("fd_3d10374c42992c.fd_3d103861bbdbd8", taxRate); // 税率
                orderDetailObj.put("fd_3d10374c42992c.fd_3d1038627086e2", orderProduct.getString("contractUntaxedA__c")); // 合同总价（不含税）
                orderDetailObj.put("fd_3d10374c42992c.fd_3d103863353d68", orderProduct.getString("priceTotal")); // 合同金额（含税）
                orderDetailObj.put("fd_3d10374c42992c.fd_3d103864a090fe", orderProduct.getString("servicePeriod__c")); // 质保期限/服务期限
                orderDetailObj.put("fd_3d10374c42992c.fd_3d103869892b76", orderProduct.getString("lineRemarks__c")); // 产品描述
                orderDetailArr.add(orderDetailObj);
            }
            formObject.put("fd_3d10374c42992c", orderDetailArr);
            logger.info(LOGGER_MSG + "formObject: " + formObject);

            // 获取所有人的OA账号 发送请求
            JSONObject ownerOaAccount = getOaAccount(order, 2);
            ResultBody resultBody = pushReqToOa("contract", contractTitle, oaApprovalId, ownerOaAccount, formObject, null);
            logger.info(LOGGER_MSG + "resultBody: " + resultBody);
            if (!Objects.equals(resultBody.getCode(), "200")) {
                logger.error(LOGGER_MSG + "推送订单数据到OA异常: " + resultBody.getMessage());
                return TfReturnMsgTools.getFailResult("推送订单数据到OA异常:" + resultBody.getMessage());
            }

            // 返回的 id 进行保存
            String newOAId = resultBody.getResult().toString();
            String objKey = pushType == 2 ? "debooking__c" : "order";
            JSONObject updateData = new JSONObject();
            updateData.put("id", pushType == 2 ? deBookingId : orderId);
            updateData.put("oaApprovalId__c", newOAId);
            updateData.put("oaApprovalStatus__c", 1);
            updateData.put("lockStatus", 2);
            updateObjetData(updateData, objKey);
            logger.info(LOGGER_MSG + "更新对象审批数据数据 " + updateData);

            // 撤回后重新提交需要修改OA的数据状态为 已提交
            if (StringUtils.isNotBlank(oaApprovalId) && (Objects.equals(oaApprovalStatus, "撤回") || Objects.equals(oaApprovalStatus, "驳回"))) {
                resubmitApprovalData(oaApprovalId, ownerOaAccount);
            }

            // 单独的方法更新附件
            JSONArray fileList = pushType == 2 ? debooking.getJSONArray("debookingAnnex__c") : order.getJSONArray("annex__c");
            UploadOAFile.syncUoloadFile(newOAId, fileKeyMap.get("contract"), fileList);

            logger.info(LOGGER_MSG + "提交成功");
            return TfReturnMsgTools.getSuccessResult("提交成功");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(LOGGER_MSG + "处理异常: " + e.getMessage());
            return TfReturnMsgTools.getFailResult("推送异常:" + e.getMessage());
        }
    }


    /**
     * 推送合同数据到OA审批 contract （合同推送的是1号订单 订单推送的是非1号订单）
     * @param
     * @return
     */
    public String pushContractToOA(Long contractId) {
        try {
            logger.info(LOGGER_MSG + "处理开始: " + contractId);

            // 合同推送的是1号订单 订单推送的是非1号订单
            String sql = "select id,contractCode,title,paymentMethod__c,opportunityId.opportunityName opportunityName,opportunityId.pmsProjectCode__c pmsProjectCode__c,clientName__c.accountName accountName," +
                    "ourCompanyName__c.name ourCompanyName,order1__c.po orderCode,order1__c.amount amount,order1__c.approximateSum__c approximateSum,order1__c.orderAmount__c orderAmount__c,responsibleSelling__c.name responsibleSellingName," +
                    "deliveryManager__c.name deliveryManagerName,deliveryManager__c.LoginName__c zrrOaAccount,deliveryManager__c.personalEmail zrrOaEmail," +
                    "departmentTeam__c,annex__c,taxRegistrationNo__c,contractBackground__c,comment,order1__c,oaApprovalId__c,oaApprovalStatus__c,entityType," +
                    "countersignNode__c.LoginName__c oaAccount,countersignNode__c.personalEmail oaEmail,ownerId.LoginName__c ownerOaAccount,ownerId.personalEmail ownerOaEmail " +
                    " from contract where id = " + contractId;
            List<JSONObject> contractRecords = xoqlService.query(sql, true).getRecords();
            if (contractRecords == null || contractRecords.size() <= 0) {
                logger.error(LOGGER_MSG + "获取合同数据异常");
                return TfReturnMsgTools.getFailResult("获取合同数据异常");
            }

            // 获取合同参数
            JSONObject contract = contractRecords.get(0);
            String contractTitle = contract.getString("title");
            Long orderId = contract.getLong("order1__c");
            Long entityType = contract.getLong("entityType");
            String oaApprovalId = contract.getString("oaApprovalId__c");
            String oaApprovalStatus = getOptionStr(contract.getJSONArray("oaApprovalStatus__c"));
            // 如果是 作废 状态，则重新提交
            if (Objects.equals(oaApprovalStatus, "作废")) {
                oaApprovalId = "";
            }
            logger.info(LOGGER_MSG + "oaApprovalId: " + oaApprovalId);
            logger.info(LOGGER_MSG + "oaApprovalStatus: " + oaApprovalStatus);


            // 判断业务类型  只推送 项目合同: 3343981728602779  预交付合同: 3344120169699944 销售其他类合同 (非标其他协议): 3373868832348783
            List<Long> typeList = Arrays.asList(3343981728602779L, 3344120169699944L, 3373868832348783L);
            if (!typeList.contains(entityType)) {
                logger.error(LOGGER_MSG + "当前合同业务类型不可提交OA审批");
                return TfReturnMsgTools.getFailResult("当前合同业务类型不可提交OA审批");
            }

            // 合同模块OA区分两个审批模块  （销售其他类合同 (非标其他协议) 为单独一个模块）
            JSONObject formObject = new JSONObject();
            String contractTemp = "contract";
            if (Objects.equals(entityType, 3373868832348783L)) {
                // 销售其他类合同(非其他协议)
                contractTemp = "specialSontract";
                formObject = getContractSpecialForm(contract);
            } else {

                // 判断 【所属部门/团队】 是否为空，进行提示
                String departmentTeamVal = contract.getString("departmentTeam__c");
                if (StringUtils.isBlank(departmentTeamVal)) {
                    logger.error(LOGGER_MSG + "当前数据【所有人】部门下的'项目所属部门团队'为空，请联系管理员进行配置");
                    return TfReturnMsgTools.getFailResult("当前数据【所有人】部门下的'项目所属部门团队'为空，请联系管理员进行配置");
                }

                // 前置条件:需要判断是否有应收计划明细 获取当前订单的应收计划明细 阶段: receivableNode__c  比列：receivableRatio__c plansReceivable_Contracts__c
                sql = "select id,receivableNode__c,receivableRatio__c,scheduledDueDate__c,paymentPeriod__c from plansReceivable_Contracts__c where contracts__c = " + contractId;
                List<JSONObject> receivableList = xoqlService.query(sql, true).getRecords();
                if (receivableList.size() <= 0) {
                    logger.error(LOGGER_MSG + "当前合同收款明细数据不可为空");
                    return TfReturnMsgTools.getFailResult("当前合同收款明细数据不可为空");
                }

                // 判断比例必须为100
                double receivableRatio = receivableList.stream().map(v -> new BigDecimal(v.getString("receivableRatio__c"))).collect(Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)).doubleValue();
                logger.info(LOGGER_MSG + "receivableRatio: " + receivableRatio);
                if (receivableRatio != 1) {
                    logger.error(LOGGER_MSG + "当前合同收款明细比例需为100%");
                    return TfReturnMsgTools.getFailResult("当前合同收款明细比例需为100%");
                }


                // 获取订单明细信息
                sql = "select id,productCode__c,productId.productName productName,productNameB__c,specificationModel__c," +
                        "unitA__c,quantity2__c,unitPrice,SF_SL__c,contractUntaxedA__c,priceTotal,servicePeriod__c,lineRemarks__c " +
                        " from orderProduct where orderId = " + orderId;
                List<JSONObject> orderProductList = xoqlService.query(sql).getRecords();
                logger.info(LOGGER_MSG + "orderProductList: " + orderProductList.size());

                // 获取应收计划
                sql = "select id,other__c from receivablePlan__c where order__c = " + orderId;
                ReceivablePlan__c receivablePlan = hcxObjectService.queryOne(sql, ReceivablePlan__c.class);

                // 拼接表单的数据
                formObject.put("fd_37b1f02aacb484", contractTitle); // 合同名
                formObject.put("fd_37b1f02d50a79a", contract.getString("opportunityName")); // 项目名称
                formObject.put("fd_37b1f027894174", contract.getString("accountName")); // 合同甲方
                formObject.put("fd_37b1f063443544", contract.getString("pmsProjectCode__c")); // pms项目编码
                formObject.put("fd_37b1f05f564030", contract.getString("ourCompanyName")); // 合同乙方
                formObject.put("fd_37b1f05c89b21a", contract.getString("orderCode")); // 销售合同编号（订单号）
                formObject.put("fd_37b1f0301f8496", contract.getString("amount")); // 合同含税总额
                formObject.put("fd_3a436ef485955a", contract.getString("orderAmount__c")); // 合同未税总额
                formObject.put("fd_37b1f02600eec6", contract.getString("responsibleSellingName")); // 责任销售

                formObject.put("fd_3a436f05f790b6", contract.getString("deliveryManagerName")); // 交付负责人
                JSONObject oaAccount = getOaAccount(contract, 3);
                formObject.put("fd_3d354f220f6d4a", oaAccount == null ? null : oaAccount.getString("LoginName")); // 交付负责人(账号)

                formObject.put("fd_38308d81c1ecc8", departmentTeamVal); // 所属部门/团队
                formObject.put("fd_3c8dfe4b57e75e", contract.getString("taxRegistrationNo__c")); // 税号
                formObject.put("fd_3d3071a37fcad2", contract.getString("approximateSum")); // 与报价概算是否一致
                formObject.put("fd_39edf9e4f6bc92", getOaAccount(contract, 1)); // 加签
                formObject.put("fd_3d3d202e1495fc", "否"); // 是否需退款
                formObject.put("fd_3d3d20289df1e6", ""); // 退款金额
                formObject.put("fd_3d54962abdddae", getOptionStr(contract.getJSONArray("paymentMethod__c"))); // 付款方式

                // 其他
                if (receivablePlan != null) {
                    formObject.put("fd_3a76b77d94325c", receivablePlan.getOther__c());
                }

                // 应收计划  1:预付 2：蓝图 3：上线 4：初验 5：终验 6：质保 7：其他
                JSONArray receivableDetailArr = new JSONArray();
                for (JSONObject receivable : receivableList) {
                    JSONObject receivableDetail = new JSONObject();
                    receivableDetail.put("fd_3d1c130b5b427a.fd_3d1c131b42b920", getOptionStr(receivable.getJSONArray("receivableNode__c"))); // 节点
                    // 比列
                    double ratio = 0;
                    if (receivable.getString("receivableRatio__c") != null) {
                        ratio = new BigDecimal(receivable.getString("receivableRatio__c")).multiply(new BigDecimal("100")).doubleValue();
                    }
                    receivableDetail.put("fd_3d1c130b5b427a.fd_3d1c131d5e7a40", ratio);
                    receivableDetail.put("fd_3d1c130b5b427a.fd_3d54964c296c42", getOptionStr(receivable.getJSONArray("paymentPeriod__c"))); // 账期
                    Long scheduledDueDate = receivable.getLong("scheduledDueDate__c");
                    if (scheduledDueDate != null) {
                        receivableDetail.put("fd_3d1c130b5b427a.fd_3d1c131e154274", HCDateUtils.longToString(scheduledDueDate, HCDateUtils.FORMATTIME)); // 时间
                    }
                    receivableDetailArr.add(receivableDetail);
                }
                formObject.put("fd_3d1c130b5b427a", receivableDetailArr);

                // 明细数据
                JSONArray orderDetailArr = new JSONArray();
                for (JSONObject orderProduct : orderProductList) {
                    JSONObject orderDetailObj = new JSONObject();
                    orderDetailObj.put("fd_3d10374c42992c.fd_3d10385af6aeb6", orderProduct.getString("productCode__c")); // 物料编码
                    orderDetailObj.put("fd_3d10374c42992c.fd_3d10385d9be716", orderProduct.getString("productName")); // 产品名称（系统）
                    orderDetailObj.put("fd_3d10374c42992c.fd_3d10385e2f70a8", orderProduct.getString("productNameB__c")); // 产品名称
                    orderDetailObj.put("fd_3d10374c42992c.fd_3d10385ed6c3de", orderProduct.getString("specificationModel__c")); // 规则型号
                    orderDetailObj.put("fd_3d10374c42992c.fd_3d10385f8deb48", orderProduct.getString("unitA__c")); // 单位
                    orderDetailObj.put("fd_3d10374c42992c.fd_3d1038602d2196", orderProduct.getString("quantity2__c")); // 数量
                    orderDetailObj.put("fd_3d10374c42992c.fd_3d103860ddf920", orderProduct.getString("unitPrice")); // 单价
                    orderDetailObj.put("fd_3d10374c42992c.fd_3d103861bbdbd8", getOptionStr(orderProduct.getJSONArray("SF_SL__c"))); // 税率
                    orderDetailObj.put("fd_3d10374c42992c.fd_3d1038627086e2", orderProduct.getString("contractUntaxedA__c")); // 合同总价（不含税）
                    orderDetailObj.put("fd_3d10374c42992c.fd_3d103863353d68", orderProduct.getString("priceTotal")); // 合同金额（含税）
                    orderDetailObj.put("fd_3d10374c42992c.fd_3d103864a090fe", orderProduct.getString("servicePeriod__c")); // 质保期限/服务期限
                    orderDetailObj.put("fd_3d10374c42992c.fd_3d103869892b76", orderProduct.getString("lineRemarks__c")); // 产品描述
                    orderDetailArr.add(orderDetailObj);
                }
                formObject.put("fd_3d10374c42992c", orderDetailArr);
            }
            logger.info(LOGGER_MSG + "formObject: " + formObject);

            // 获取所有人的OA账号 发送请求
            JSONObject ownerOaAccount = getOaAccount(contract, 2);
            ResultBody resultBody = pushReqToOa(contractTemp, contractTitle, oaApprovalId, ownerOaAccount, formObject, null);
            logger.info(LOGGER_MSG + "resultBody: " + resultBody);
            if (!Objects.equals(resultBody.getCode(), "200")) {
                logger.error(LOGGER_MSG + "推送合同数据到OA异常: " + resultBody.getMessage());
                return TfReturnMsgTools.getFailResult("推送合同数据到OA异常:" + resultBody.getMessage());
            }

            // 返回的 id 进行保存
            String newOAId = resultBody.getResult().toString();
            Contract upContract = new Contract();
            upContract.setId(contractId);
            upContract.setOaApprovalId__c(newOAId);
            upContract.setOaApprovalStatus__c(1);
            upContract.setLockStatus(2);
            Boolean update = hcxObjectService.update(upContract);
            logger.info(LOGGER_MSG + "update: " + update);

            // 撤回后重新提交需要修改OA的数据状态为 已提交
            if (StringUtils.isNotBlank(oaApprovalId) && (Objects.equals(oaApprovalStatus, "撤回") || Objects.equals(oaApprovalStatus, "驳回"))) {
                resubmitApprovalData(oaApprovalId, ownerOaAccount);
            }

            // 单独的方法更新附件
            JSONArray fileList = contract.getJSONArray("annex__c");
            UploadOAFile.syncUoloadFile(newOAId, fileKeyMap.get(contractTemp), fileList);

            logger.info(LOGGER_MSG + "提交成功");
            return TfReturnMsgTools.getSuccessResult("提交成功");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(LOGGER_MSG + "处理异常: " + e.getMessage());
            return TfReturnMsgTools.getFailResult("推送异常:" + e.getMessage());
        }
    }

    /**
     * 获取合同特殊的表单值 -- 销售其他类合同 (非标其他协议)
     * @param contract
     * @return
     */
    public JSONObject getContractSpecialForm(JSONObject contract) {
        // 拼接表单的数据
        JSONObject formObject = new JSONObject();
        formObject.put("fd_37b1e89e98e5d2", contract.getString("title")); // 合同名
        formObject.put("fd_37b1e8b187282a", contract.getString("accountName")); // 合同甲方
        formObject.put("fd_37b1e8b3b79336", contract.getString("ourCompanyName")); // 合同乙方
        formObject.put("fd_386848b081e74c", contract.getString("departmentTeam__c")); // 项目所属部门/团队
        formObject.put("fd_37b1eaf102db0a", contract.getString("contractBackground__c")); // 合同背景
        formObject.put("fd_3ad82a3ae89c74", contract.getString("comment")); // 其他背注
        formObject.put("fd_38a1855a3117c8", getOaAccount(contract,1)); // 加签
        formObject.put("fd_3d9382365872b2", contract.getString("contractCode")); // 销售合同编号
        return formObject;
    }




}
